צרו חוויות רשת זורמות דמויות-אפליקציה. מדריך מקיף זה סוקר את הפסאודו-אלמנטים של CSS View Transitions לעיצוב מעברי עמודים דינמיים, עם דוגמאות ושיטות עבודה מומלצות.
שליטה במעברי תצוגה ב-CSS: צלילת עומק לעיצוב פסאודו-אלמנטים
בנוף המתפתח תמיד של פיתוח אתרי אינטרנט, המרדף אחר חווית משתמש חלקה, זורמת ומרתקת הוא קבוע. במשך שנים, מפתחים שאפו לגשר על הפער בין האינטרנט ליישומים נייטיביים, במיוחד בכל הנוגע לחלקות של מעברי עמודים. ניווט אינטרנטי מסורתי גורם לעיתים קרובות לטעינה מחדש של עמוד שלם—מסך לבן ריק ששובר לרגע את חווית המשתמש. יישומי עמוד יחיד (SPAs) הקלו על כך, אך יצירת מעברים מותאמים אישית ומשמעותיים נותרה משימה מורכבת ולעיתים שברירית, המסתמכת בכבדות על ספריות JavaScript וניהול מצב מורכב.
כאן נכנס לתמונה ה-API של מעברי תצוגה ב-CSS (CSS View Transitions API), טכנולוגיה משנה משחק שעומדת לחולל מהפכה באופן שבו אנו מטפלים בשינויים בממשק המשתמש באינטרנט. API רב עוצמה זה מספק מנגנון פשוט אך גמיש להפליא ליצירת אנימציה בין מצבי DOM שונים, מה שהופך את יצירת החוויות המלוטשות, דמויות-האפליקציה, שהמשתמשים מצפים להן, לקלה מתמיד. בלב העוצמה של API זה נמצא סט של פסאודו-אלמנטים חדשים ב-CSS. אלו אינם סלקטורים טיפוסיים; הם אלמנטים דינמיים וזמניים שנוצרים על ידי הדפדפן כדי לתת לכם שליטה פרטנית על כל שלב במעבר. מדריך זה ייקח אתכם לצלילת עומק לתוך עץ הפסאודו-אלמנטים הזה, ויבחן כיצד לעצב כל רכיב כדי לבנות אנימציות מדהימות, ביצועיסטיות ונגישות עבור קהל גלובלי.
האנטומיה של מעבר תצוגה
לפני שנוכל לעצב מעבר, עלינו להבין מה קורה מאחורי הקלעים כאשר הוא מופעל. כאשר אתם יוזמים מעבר תצוגה (לדוגמה, על ידי קריאה ל-document.startViewTransition()), הדפדפן מבצע סדרה של שלבים:
- לכידת המצב הישן: הדפדפן מצלם "צילום מסך" של מצב העמוד הנוכחי.
- עדכון ה-DOM: הקוד שלכם מבצע את השינויים ב-DOM (למשל, ניווט לתצוגה חדשה, הוספה או הסרה של אלמנטים).
- לכידת המצב החדש: לאחר השלמת עדכון ה-DOM, הדפדפן מצלם צילום מסך של המצב החדש.
- בניית עץ הפסאודו-אלמנטים: הדפדפן בונה עץ זמני של פסאודו-אלמנטים בשכבת-העל של העמוד. עץ זה מכיל את התמונות שנלכדו של המצבים הישן והחדש.
- הנפשה: אנימציות CSS מוחלות על פסאודו-אלמנטים אלה, ויוצרות מעבר חלק מהמצב הישן לחדש. ברירת המחדל היא מעבר הצלבה (cross-fade) פשוט.
- ניקוי: לאחר השלמת האנימציות, עץ הפסאודו-אלמנטים מוסר, והמשתמש יכול לקיים אינטראקציה עם ה-DOM החדש והחי.
המפתח להתאמה אישית הוא עץ הפסאודו-אלמנטים הזמני הזה. חשבו עליו כעל סט של שכבות בכלי עיצוב, המונחות באופן זמני על גבי העמוד שלכם. יש לכם שליטת CSS מלאה על שכבות אלה. הנה המבנה שתעבדו איתו:
- ::view-transition
- ::view-transition-group(*)
- ::view-transition-image-pair(*)
- ::view-transition-old(*)
- ::view-transition-new(*)
- ::view-transition-image-pair(*)
- ::view-transition-group(*)
בואו נפרט מה כל אחד מהפסאודו-אלמנטים הללו מייצג.
צוות הפסאודו-אלמנטים
::view-transition: זהו השורש של המבנה כולו. זהו אלמנט יחיד הממלא את אזור התצוגה (viewport) ויושב מעל כל תוכן אחר בעמוד. הוא משמש כקונטיינר לכל הקבוצות המשתתפות במעבר והוא מקום מצוין להגדיר מאפייני מעבר כלליים כמו משך זמן או פונקציית תזמון.
::view-transition-group(*): עבור כל אלמנט נפרד במעבר (המזוהה על ידי מאפיין ה-CSS view-transition-name), נוצרת קבוצה. פסאודו-אלמנט זה אחראי על הנפשת המיקום והגודל של התוכן שלו. אם יש לכם כרטיס שעובר מצד אחד של המסך לצד אחר, זה ה-::view-transition-group שזז בפועל.
::view-transition-image-pair(*): מקונן בתוך הקבוצה, אלמנט זה פועל כקונטיינר ומסכת חיתוך (clipping mask) עבור התצוגות הישנה והחדשה. תפקידו העיקרי הוא לשמר אפקטים כמו border-radius או transform במהלך האנימציה ולטפל באנימציית ה-cross-fade המוגדרת כברירת מחדל.
::view-transition-old(*): זה מייצג את "צילום המסך" או התצוגה המרונדרת של האלמנט במצבו הישן (לפני שינוי ה-DOM). כברירת מחדל, הוא מונפש מ-opacity: 1 ל-opacity: 0.
::view-transition-new(*): זה מייצג את "צילום המסך" או התצוגה המרונדרת של האלמנט במצבו החדש (לאחר שינוי ה-DOM). כברירת מחדל, הוא מונפש מ-opacity: 0 ל-opacity: 1.
השורש: עיצוב הפסאודו-אלמנט ::view-transition
הפסאודו-אלמנט ::view-transition הוא הקנבס שעליו מצוירת כל האנימציה שלכם. כקונטיינר ברמה העליונה, הוא המקום האידיאלי להגדיר מאפיינים שצריכים לחול באופן גלובלי על המעבר. כברירת מחדל, הדפדפן מספק סט של אנימציות, אך ניתן בקלות לדרוס אותן.
לדוגמה, מעבר ברירת המחדל הוא cross-fade שנמשך 250 אלפיות השנייה. אם תרצו לשנות זאת עבור כל מעבר באתר שלכם, תוכלו למקד את פסאודו-אלמנט השורש:
::view-transition {
animation-duration: 500ms;
animation-timing-function: ease-in-out;
}
כלל פשוט זה גורם כעת לכל מעברי ברירת המחדל של העמוד להימשך פי שניים יותר זמן ולהשתמש בעקומת 'ease-in-out', מה שמעניק להם תחושה מעט שונה. למרות שניתן להחיל כאן אנימציות מורכבות, בדרך כלל עדיף להשתמש בו להגדרת תזמון והאצה אוניברסליים, ולהשאיר לפסאודו-אלמנטים הספציפיים יותר לטפל בכוריאוגרפיה המפורטת.
קיבוץ ומתן שמות: העוצמה של `view-transition-name`
ישר מהקופסה, ללא כל עבודה נוספת, ה-API של View Transition מספק cross-fade עבור העמוד כולו. זה מטופל על ידי קבוצת פסאודו-אלמנטים יחידה עבור השורש. העוצמה האמיתית של ה-API נחשפת כאשר רוצים להנפיש אלמנטים ספציפיים ואינדיבידואליים בין מצבים. לדוגמה, לגרום לתמונה ממוזערת של מוצר בדף רשימה לגדול ולעבור בצורה חלקה למיקום תמונת המוצר הראשית בדף פרטים.
כדי לומר לדפדפן ששני אלמנטים במצבי DOM שונים הם זהים מבחינה רעיונית, משתמשים במאפיין ה-CSS view-transition-name. יש להחיל מאפיין זה הן על אלמנט ההתחלה והן על אלמנט הסיום.
/* בקובץ ה-CSS של דף הרשימה */
.product-thumbnail {
view-transition-name: product-image;
}
/* בקובץ ה-CSS של דף הפרטים */
.main-product-image {
view-transition-name: product-image;
}
על ידי מתן אותו שם ייחודי לשני האלמנטים ('product-image' במקרה זה), אתם מורים לדפדפן: "במקום רק לעמעם את העמוד הישן ולהבהיר את העמוד החדש, צור מעבר מיוחד עבור אלמנט ספציפי זה." הדפדפן ייצור כעת ::view-transition-group(product-image) ייעודי כדי לטפל באנימציה שלו בנפרד ממעבר השורש. זהו הרעיון הבסיסי המאפשר את אפקט המעבר הפופולרי של "שינוי צורה" (morphing) או "אלמנט משותף".
הערה חשובה: בכל רגע נתון במהלך מעבר, view-transition-name חייב להיות ייחודי. לא יכולים להיות שני אלמנטים גלויים עם אותו שם בו-זמנית.
עיצוב מעמיק: פסאודו-אלמנטים הליבה
לאחר שנתנו שמות לאלמנטים שלנו, נוכל לצלול לעיצוב הפסאודו-אלמנטים הספציפיים שהדפדפן יוצר עבורם. כאן תוכלו ליצור אנימציות מותאמות אישית ואקספרסיביות באמת.
`::view-transition-group(name)`: המזיז
האחריות הבלעדית של הקבוצה היא לעבור מהגודל והמיקום של האלמנט הישן לגודל והמיקום של האלמנט החדש. היא אינה מכילה את המראה של התוכן עצמו, אלא רק את התיבה התוחמת שלו. חשבו עליה כמסגרת נעה.
כברירת מחדל, הדפדפן מנפיש את מאפייני ה-transform וה-width/height שלה. ניתן לדרוס זאת כדי ליצור אפקטים שונים. לדוגמה, תוכלו להוסיף קשת לתנועה שלה על ידי הנפשתה לאורך נתיב מעוקל, או לגרום לה לגדול ולקטון במהלך מסעה.
::view-transition-group(product-image) {
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
בדוגמה זו, אנו מחילים פונקציית האצה ספציפית רק על תנועת תמונת המוצר, מה שגורם לה להרגיש דינמית ופיזית יותר, מבלי להשפיע על מעבר ברירת המחדל של שאר העמוד.
`::view-transition-image-pair(name)`: החותך והמעמעם
מקונן בתוך הקבוצה הנעה, ה-image-pair מחזיק את התצוגות הישנה והחדשה. הוא פועל כמסכת חיתוך, כך שאם לאלמנט שלכם יש border-radius, ה-image-pair מבטיח שהתוכן יישאר חתוך עם אותו רדיוס לאורך כל אנימציית הגודל והמיקום. תפקידו העיקרי השני הוא לתזמר את ה-cross-fade ברירת המחדל בין התוכן הישן והחדש.
ייתכן שתרצו לעצב אלמנט זה כדי להבטיח עקביות חזותית או כדי ליצור אפקטים מתקדמים יותר. מאפיין מפתח שיש לקחת בחשבון הוא isolation: isolate. זה חיוני אם אתם מתכננים להשתמש באפקטים מתקדמים של mix-blend-mode על הילדים (הישן והחדש), מכיוון שהוא יוצר הקשר ערימה חדש ומונע מהמיזוג להשפיע על אלמנטים מחוץ לקבוצת המעבר.
::view-transition-image-pair(product-image) {
isolation: isolate;
}
`::view-transition-old(name)` ו-`::view-transition-new(name)`: כוכבי המופע
אלו הם הפסאודו-אלמנטים המייצגים את המראה החזותי של האלמנט שלכם לפני ואחרי שינוי ה-DOM. כאן תתבצע רוב עבודת האנימציה המותאמת אישית שלכם. כברירת מחדל, הדפדפן מריץ עליהם אנימציית cross-fade פשוטה באמצעות opacity ו-mix-blend-mode. כדי ליצור אנימציה מותאמת אישית, עליכם תחילה לכבות את אנימציית ברירת המחדל.
::view-transition-old(name),
::view-transition-new(name) {
animation: none;
}
לאחר שאנימציית ברירת המחדל מושבתת, אתם חופשיים להחיל אנימציה משלכם. בואו נבחן כמה דפוסים נפוצים.
אנימציה מותאמת אישית: החלקה (Slide)
במקום cross-fade, בואו נגרום לתוכן של קונטיינר להחליק פנימה. לדוגמה, בעת ניווט בין מאמרים, אנו רוצים שהטקסט של המאמר החדש יחליק פנימה מימין בזמן שהטקסט הישן מחליק החוצה לשמאל.
ראשית, הגדירו את ה-keyframes:
@keyframes slide-from-right {
from { transform: translateX(100%); }
to { transform: translateX(0); }
}
@keyframes slide-to-left {
from { transform: translateX(0); }
to { transform: translateX(-100%); }
}
כעת, החילו את האנימציות הללו על הפסאודו-אלמנטים הישן והחדש עבור האלמנט בשם 'article-content'.
::view-transition-old(article-content) {
animation: 300ms ease-out forwards slide-to-left;
}
::view-transition-new(article-content) {
animation: 300ms ease-out forwards slide-from-right;
}
אנימציה מותאמת אישית: היפוך תלת-ממדי (3D Flip)
לקבלת אפקט דרמטי יותר, ניתן ליצור היפוך כרטיס תלת-ממדי. זה דורש הנפשת המאפיין transform עם rotateY וגם ניהול של backface-visibility.
/* הקבוצה זקוקה להקשר תלת-ממדי */
::view-transition-group(card-flipper) {
transform-style: preserve-3d;
}
/* גם ה-image-pair צריך לשמר את ההקשר התלת-ממדי */
::view-transition-image-pair(card-flipper) {
transform-style: preserve-3d;
}
/* התצוגה הישנה מתהפכת מ-0 ל-180- מעלות */
::view-transition-old(card-flipper) {
animation: 600ms ease-in forwards flip-out;
backface-visibility: hidden;
}
/* התצוגה החדשה מתהפכת מ-180 ל-0 מעלות */
::view-transition-new(card-flipper) {
animation: 600ms ease-out forwards flip-in;
backface-visibility: hidden;
}
@keyframes flip-out {
from { transform: rotateY(0deg); }
to { transform: rotateY(-180deg); }
}
@keyframes flip-in {
from { transform: rotateY(180deg); }
to { transform: rotateY(0deg); }
}
דוגמאות מעשיות וטכניקות מתקדמות
תיאוריה היא שימושית, אבל יישום מעשי הוא המקום שבו אנו לומדים באמת. בואו נעבור על כמה תרחישים נפוצים וכיצד לפתור אותם באמצעות פסאודו-אלמנטים של מעבר תצוגה.
דוגמה: תמונת כרטיס משנה-צורה ("Morphing")
זהו מעבר האלמנט המשותף הקלאסי. דמיינו גלריה של פרופילי משתמשים. כל פרופיל הוא כרטיס עם אוואטר. כאשר לוחצים על כרטיס, מנווטים לדף פרטים שבו אותו אוואטר מוצג באופן בולט בראש הדף.
שלב 1: הקצאת שמות
בדף הגלריה שלכם, תמונת האוואטר מקבלת שם. השם צריך להיות ייחודי לכל כרטיס, לדוגמה, מבוסס על מזהה המשתמש.
/* ב-gallery-item.css */
.card-avatar { view-transition-name: avatar-user-123; }
בדף פרטי הפרופיל, האוואטר הגדול בכותרת מקבל בדיוק את אותו השם.
/* ב-profile-page.css */
.profile-header-avatar { view-transition-name: avatar-user-123; }
שלב 2: התאמה אישית של האנימציה
כברירת מחדל, הדפדפן יזיז וישנה את גודל האוואטר, אך הוא גם יעשה cross-fade לתוכן. אם התמונה זהה, מעבר זה מיותר ויכול לגרום להבהוב קל. אנחנו יכולים לבטל אותו.
/* הכוכבית (*) כאן היא תו כללי (wildcard) לכל קבוצה בעלת שם */
::view-transition-image-pair(*) {
/* השבתת מעבר ברירת המחדל */
animation-duration: 0s;
}
רגע, אם נשבית את המעבר, איך התוכן מתחלף? עבור אלמנטים משותפים שבהם התצוגות הישנה והחדשה זהות, הדפדפן חכם מספיק כדי להשתמש בתצוגה אחת בלבד לכל המעבר. ה-`image-pair` למעשה מחזיק רק תמונה אחת, כך שהשבתת המעבר פשוט חושפת את האופטימיזציה הזו. עבור אלמנטים שבהם התוכן באמת משתנה, תצטרכו אנימציה מותאמת אישית במקום מעבר ברירת המחדל.
טיפול בשינויים ביחס הגובה-רוחב (Aspect Ratio)
אתגר נפוץ מתעורר כאשר אלמנט במעבר משנה את יחס הגובה-רוחב שלו. לדוגמה, תמונה ממוזערת נופית ביחס 16:9 בדף רשימה עשויה לעבור לאוואטר ריבועי ביחס 1:1 בדף הפרטים. התנהגות ברירת המחדל של הדפדפן היא להנפיש את הרוחב והגובה באופן עצמאי, מה שגורם לתמונה להיראות מעוכה או מתוחה במהלך המעבר.
הפתרון אלגנטי. אנו נותנים ל-::view-transition-group לטפל בשינוי הגודל והמיקום, אך אנו דורסים את העיצוב של התמונות הישנה והחדשה שבתוכו.
המטרה היא לגרום ל"צילומי המסך" הישן והחדש למלא את הקונטיינר שלהם מבלי להתעוות. אנו יכולים לעשות זאת על ידי הגדרת הרוחב והגובה שלהם ל-100% ולאפשר למאפיין ברירת המחדל של הדפדפן `object-fit` (שיורש מהאלמנט המקורי) לטפל בשינוי הגודל כראוי.
::view-transition-old(hero-image),
::view-transition-new(hero-image) {
/* מניעת עיוות על ידי מילוי הקונטיינר */
width: 100%;
height: 100%;
/* דריסת ה-cross-fade ברירת המחדל כדי לראות את האפקט בבירור */
animation: none;
}
עם ה-CSS הזה, ה-`image-pair` ינפיש בצורה חלקה את יחס הגובה-רוחב שלו, והתמונות בפנים ייחתכו או יקבלו שוליים שחורים (תלוי בערך ה-`object-fit` שלהן), בדיוק כפי שהיו בקונטיינר רגיל. לאחר מכן תוכלו להוסיף אנימציות מותאמות אישית משלכם, כמו cross-fade, על גבי הגיאומטריה המתוקנת הזו.
ניפוי באגים ותמיכת דפדפנים
עיצוב אלמנטים שקיימים רק לשבריר שנייה יכול להיות מסובך. למרבה המזל, דפדפנים מודרניים מספקים כלי מפתחים מצוינים לשם כך. בכלי המפתחים של Chrome או Edge, תוכלו לעבור לחלונית "Animations", וכאשר אתם מפעילים מעבר תצוגה, תוכלו להשהות אותו. כשהאנימציה מושהית, תוכלו להשתמש בחלונית "Elements" כדי לבדוק את כל עץ הפסאודו-אלמנטים של `::view-transition` בדיוק כמו כל חלק אחר ב-DOM. תוכלו לראות את הסגנונות המוחלים ואף לשנות אותם בזמן אמת כדי לשכלל את האנימציות שלכם.
נכון לסוף 2023, ה-API של View Transitions נתמך בדפדפנים מבוססי Chromium (כרום, אדג', אופרה). יישומים נמצאים בתהליך פיתוח עבור פיירפוקס וספארי. זה הופך אותו למועמד מושלם לשיפור הדרגתי (progressive enhancement). משתמשים עם דפדפנים תומכים מקבלים חוויה משופרת ומהנה, בעוד שמשתמשים בדפדפנים אחרים מקבלים את הניווט הסטנדרטי והמיידי. ניתן לבדוק תמיכה ב-CSS:
@supports (view-transition: none) {
/* כל סגנונות ה-view-transition יופיעו כאן */
::view-transition-old(my-element) { ... }
}
שיטות עבודה מומלצות עבור קהל גלובלי
בעת יישום אנימציות, חיוני לקחת בחשבון את המגוון הרחב של משתמשים ומכשירים ברחבי העולם.
ביצועים: אנימציות צריכות להיות מהירות וזורמות. הקפידו להנפיש מאפייני CSS שזול לדפדפן לעבד, בעיקר transform ו-opacity. הנפשת מאפיינים כמו width, height, או margin יכולה לגרום לחישובים מחדש של הפריסה בכל פריים, מה שמוביל לגמגום וחוויה ירודה, במיוחד במכשירים חלשים יותר.
נגישות: חלק מהמשתמשים חווים בחילת תנועה או אי נוחות מאנימציות. כל מערכות ההפעלה הגדולות מספקות העדפת משתמש להפחתת תנועה. עלינו לכבד זאת. שאילתת המדיה prefers-reduced-motion מאפשרת לכם להשבית או לפשט את האנימציות שלכם עבור משתמשים אלה.
@media (prefers-reduced-motion: reduce) {
::view-transition-group(*),
::view-transition-old(*),
::view-transition-new(*) {
/* דלגו על כל האנימציות המותאמות אישית והשתמשו במעבר מהיר ופשוט */
animation: none !important;
}
}
חווית משתמש (UX): מעברים טובים הם תכליתיים. הם צריכים להנחות את תשומת לב המשתמש ולספק הקשר לגבי השינוי המתרחש בממשק המשתמש. אנימציה איטית מדי יכולה לגרום ליישום להרגיש איטי, בעוד שאחת ראוותנית מדי יכולה להסיח את הדעת. שאפו למשכי מעבר בין 200ms ל-500ms. המטרה היא שהאנימציה תורגש יותר מאשר תיראה.
סיכום: העתיד הוא זורם
ה-API של CSS View Transitions, ובמיוחד עץ הפסאודו-אלמנטים העוצמתי שלו, מייצג קפיצת דרך מונומנטלית עבור ממשקי משתמש באינטרנט. הוא מספק למפתחים ערכת כלים נייטיבית, ביצועיסטית וניתנת להתאמה אישית גבוהה ליצירת סוג המעברים הזורמים והמצביים שהיו פעם נחלתם הבלעדית של יישומים נייטיביים. על ידי הבנת התפקידים של ::view-transition, ::view-transition-group, וזוגות התמונות הישנה/חדשה, תוכלו לעבור מעבר למעברים פשוטים ולתזמר אנימציות מורכבות ומשמעותיות המשפרות את השימושיות ומשמחות את המשתמשים.
ככל שתמיכת הדפדפנים תתרחב, API זה יהפוך לחלק חיוני בארגז הכלים של מפתח הפרונט-אנד המודרני. על ידי אימוץ יכולותיו והקפדה על שיטות עבודה מומלצות לביצועים ונגישות, נוכל לבנות רשת שהיא לא רק פונקציונלית יותר, אלא גם יפה ואינטואיטיבית יותר עבור כולם, בכל מקום.